
/*
 *Copyright (c) 2024 Black Sesame Technologies
 *
 *Licensed under the Apache License, Version 2.0 (the "License");
 *you may not use this file except in compliance with the License.
 *You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 *Unless required by applicable law or agreed to in writing, software
 *distributed under the License is distributed on an "AS IS" BASIS,
 *WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *See the License for the specific language governing permissions and
 *limitations under the License.
*/
#ifndef _UTILITY_LITE_H
#define _UTILITY_LITE_H

#include "kernel.h"

#define __wait_timeout_tick_decrement(timeout)  \
({                                              \
    delaySoft(5);                               \
    timeout --;                                 \
})

#define ___wait_cond_timeout(condition)					\
({									\
	bool __cond = (condition);					\
	if (__cond && !__ret)						\
		__ret = 1;						\
	__cond || !__ret;						\
})

#define __wait_event_timeout(condition, timeout)    \
({                                                  \
    long count = timeout;                           \
    while(count) {                                  \
        if(condition) {                             \
            break;                                  \
        }                                           \
        __wait_timeout_tick_decrement(count);       \
    }                                               \
    count;                                          \
})

#define wait_event_timeout(condition, timeout)			\
({									\
	long __ret = timeout;						\
	if (!___wait_cond_timeout(condition))				\
		__ret = __wait_event_timeout(condition, timeout);	\
	__ret;								\
})

static __inline unsigned short
__bswap_16 (unsigned short __x)
{
  return (__x >> 8) | (__x << 8);
}

static __inline unsigned int
__bswap_32 (unsigned int __x)
{
  return (__bswap_16 (__x & 0xffff) << 16) | (__bswap_16 (__x >> 16));
}

static __inline unsigned long long
__bswap_64 (unsigned long long __x)
{
  return (((unsigned long long) __bswap_32 (__x & 0xffffffffull)) << 32) | (__bswap_32 (__x >> 32));
}

#ifndef __BIG_ENDIAN
# define __BIG_ENDIAN 4321
#endif
#ifndef __LITTLE_ENDIAN
# define __LITTLE_ENDIAN 1234
#endif

#ifndef __BYTE_ORDER
# define __BYTE_ORDER __LITTLE_ENDIAN
#endif

#if __BYTE_ORDER == __BIG_ENDIAN
#define cpu_to_le16 __bswap_16
#define cpu_to_le32 __bswap_32
#define cpu_to_le64 __bswap_64
#define le16_to_cpu __bswap_16
#define le32_to_cpu __bswap_32
#define le64_to_cpu __bswap_64
#define cpu_to_be16
#define cpu_to_be32
#define cpu_to_be64
#define be16_to_cpu
#define be32_to_cpu
#define be64_to_cpu
#else
#define cpu_to_le16
#define cpu_to_le32
#define cpu_to_le64
#define le16_to_cpu
#define le32_to_cpu
#define le64_to_cpu
#define cpu_to_be16 __bswap_16
#define cpu_to_be32 __bswap_32
#define cpu_to_be64 __bswap_64
#define be16_to_cpu __bswap_16
#define be32_to_cpu __bswap_32
#define be64_to_cpu __bswap_64
#endif

/**
 * upper_32_bits - return bits 32-63 of a number
 * @n: the number we're accessing
 *
 * A basic shift-right of a 64- or 32-bit quantity.  Use this to suppress
 * the "right shift count >= width of type" warning when that quantity is
 * 32-bits.
 */
#define upper_32_bits(n) ((u32)(((n) >> 16) >> 16))

/**
 * lower_32_bits - return bits 0-31 of a number
 * @n: the number we're accessing
 */
#define lower_32_bits(n) ((u32)(n))

# define __WORDSIZE     32

/* Not standard, but glibc defines it */
#define BITS_PER_LONG __WORDSIZE

#define BIT_MASK(nr)		(1UL << ((nr) % BITS_PER_LONG))
#define WORD_BIT(nr)		((nr) / BITS_PER_LONG)
#define BITS_PER_BYTE		8
#define BITS_TO_U64(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u64))
#define BITS_TO_U32(nr)		DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(u32))
#define BITS_TO_BYTES(nr)	DIV_ROUND_UP(nr, BITS_PER_BYTE)


static inline int set_bit(unsigned int nr, volatile unsigned int *p)
{
	unsigned int mask = BIT_MASK(nr);

	p += WORD_BIT(nr);
	if ((*p) & mask)
		return 1;

	*p |= mask;  

	return 0;
}

static inline int test_and_set_bit(unsigned int nr, volatile unsigned int *p)
{
	unsigned int old;
	unsigned int mask = BIT_MASK(nr);

	p += WORD_BIT(nr);
	if ((*p) & mask)
		return 1;

	old = (*p);

	*p = old | mask;
	
	return !!(old & mask);
}

static inline int
test_and_set_bit_lock(unsigned int nr, unsigned int *addr)
{
	return test_and_set_bit(nr, addr);
}

static inline void
clear_bit(unsigned int nr, volatile unsigned int * addr)
{
	unsigned int mask = BIT_MASK(nr);

	addr += WORD_BIT(nr);

	if (((*addr) & mask) != 0){
		*addr &= ~mask; 
	}
}

static inline void
clear_bit_unlock(unsigned int nr, volatile unsigned int * addr)
{
	clear_bit(nr, addr);
}

static inline int
test_bit(int nr, volatile void * addr)
{
	return (1UL & (((int *) addr)[nr >> 5] >> (nr & 31))) != 0UL;
}

typedef void (*F_postFn)(void);

typedef void (*F_cmdFn)(unsigned int para);

typedef enum
{
    safety2rt = 0,
    safety2sw,
    safety2SocA78,
	safety2Db,
	safety2SocR5,
	safety2Hifi,
	safety2Cv,

    rt2safety,
	rt2sw,
	rt2Db,
	rt2SocR5,
	rt2Hifi,
	rt2Cv,
	rt2SocA78,

    sw2safety,
	sw2rt,
	sw2SocA78,
	sw2Db,
	sw2SocR5,
	sw2Hifi,
	sw2Cv,

	SocA782safety,
	SocA782sw,
	SocA782rt,
	SocA782Db,
	SocA782SocR5,
	SocA782Hifi,
	SocA782Cv,
} Intr_ChangeType;

typedef struct cmd_struct{
	F_cmdFn cmdFn;
	unsigned int para;		
	unsigned int attr;		
	const char *cmdName;
	const char *description;
}T_Cmd_list;

#define CMD_ATTR_AUTO_TEST 0X1
#define CMD_ATTR_NO_AUTO_TEST 0X0
#define CMD_ATTR_AUTO_LAST 0x8

#define CMD_DEFINE(__cmdName,__cmdFn, __para,  __description,__attr)       \
    __attribute__ ((section(".section_test_cmd_table")))        \
    struct cmd_struct _section_item_##__cmdName##_cmd = {  \
		.cmdFn = __cmdFn,								\
		.para = __para,								\
		.attr = __attr, 								\
        .cmdName =  #__cmdName,           	\
        .description =__description,  	\
}

/*soft delay*/
void delaySoft(int loopcnt);


/*dump mem info by input*/
void dumpMem(unsigned int para);

/*set mem by 32 bit*/
void setMem32(unsigned para);


/*show all cmd support*/
void helpCmd(unsigned int para);	

/*get string(cmd)*/
int getString(char *cmd_buf, int len);

/*get a hex value*/
int getHex(unsigned int *value);

/*
4 bit hex to char
*/
int putHex(unsigned int value);

/*
char buffer, 4 bit hex to char
*/
void putStr(unsigned char *ch,unsigned int length);

/*
memset by byte
*/
void memSet8(void *buf,unsigned char val, unsigned int length);


/*
set register32 from buffer
*/
void setReg32FromBuf(unsigned int dstReg,unsigned int *buf,unsigned int length);

int memCmp8(void *buf1, void *buf2, unsigned int length);

/*
memory  compare,return err cnt
*/
void * memCpy8(void *srcBuf, void *dstBuf, unsigned int length);

unsigned int *memCpy32(unsigned int *dest, unsigned int *src, unsigned int count);

int memReadWriteTst(unsigned int ddrMemStartAddr,unsigned int ddrMemEndAddr);

/*
 * info = what info would print
 */
void waitInputQ(char *info);


/*
dump value by word(int)
*/
void dumpIntVal(unsigned int *pBuf,unsigned int len32);

/*
change hex string to char
*/
int str2ValStartTail(char *str,unsigned int *val, int valLength8);

int str2ValStartHead(char *str,unsigned int *val, int valLength8);

/*run Cmd we support*/
int runCmd(const char * cmdBuf);






#define BigtoLittle32(A)    ((((unsigned int)(A) & 0xff000000) >> 24)|\
							 (((unsigned int)(A) & 0x00ff0000) >> 8)|\
                             (((unsigned int)(A) & 0x0000ff00) << 8)|\
                             (((unsigned int)(A) & 0x000000ff) << 24)) 


/*
buffer bit to lit by word (int)
*/
void Buffer_Big2Lit32(unsigned int *pBuf,unsigned int len32);

int getRegTemp(unsigned int regVal);

void system_sleep(void);

unsigned int timer_start(unsigned int timer_addr);

unsigned int get_timer(unsigned int timer_addr);

void Intr_interconversion(Intr_ChangeType ChangeType ,unsigned int* int_list , unsigned int int_num);
extern unsigned int String2Decimal(char *string, unsigned char len);
extern int str2hex(const char *str, unsigned int *value);
void cmd_main(void);
extern int str2uint(const char *str, unsigned int *value);
extern int getUint(unsigned int *value);


void auto_main(void);

#endif /* _UTILITY_LITE_H */
